#include "ds18b20.h"

void DS18B20_Out(){														
	DS18B20_RCC_APBClkCmd(DS18B20_GPIO_CLK,ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;					//设置为推挽输出模式
	GPIO_InitStruct.GPIO_Pin=DS18B20_GPIO_Pin;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(DS18B20_GPIO_PORT,&GPIO_InitStruct);
}

void DS18B20_In(){														
	DS18B20_RCC_APBClkCmd(DS18B20_GPIO_CLK,ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;		//设置为浮空输入模式
	GPIO_InitStruct.GPIO_Pin=DS18B20_GPIO_Pin;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(DS18B20_GPIO_PORT,&GPIO_InitStruct);
}

void DS18B20_High(){
	GPIO_SetBits(DS18B20_GPIO_PORT,DS18B20_GPIO_Pin);
}

void DS18B20_Low(){
	GPIO_ResetBits(DS18B20_GPIO_PORT,DS18B20_GPIO_Pin);
}

uint8_t DS18B20_ReadStatus(){
	return GPIO_ReadInputDataBit(DS18B20_GPIO_PORT,DS18B20_GPIO_Pin);
}

/**
 * DS18B20初始化
 */
void DS18B20_Init(){
	DS18B20_Out();			//控制总线
	DS18B20_Low();			//拉低总线超过480us
	Delay_us(500);
	DS18B20_High();			//上拉电阻拉高，防抖
	Delay_us(2);
	DS18B20_In();				//释放总线
}

/**
 * 检测DS18B20是否存在
 */
uint8_t DS18B20_Check(){
	uint16_t timeout=100;
	while(DS18B20_ReadStatus()==SET && timeout){		//等待拉低60-240us，判断是否存在传感器
		timeout--;
		Delay_us(1);
	}
	if(!timeout){
		return 0;
	}
	
	timeout=300;
	while(DS18B20_ReadStatus()==RESET && timeout){	//等待传感器拉高
		timeout--;
		Delay_us(1);
	}
	if(!timeout){
		return 0;
	}
	return 1;
}

/**
  * @brief  用于执行写命令
  * @param  dat: 待写入的数据
  * @retval None
  */
void DS18B20_Write(uint8_t dat){
	DS18B20_Out();						//控制总线
	for(int i=0;i<8;i++){
		if(dat & 0x01){
			DS18B20_Low();				//拉低电平时间大于1us
			Delay_us(2);
			DS18B20_High();				//在15us内拉高总线
			Delay_us(100);
		}else{
			DS18B20_Low();				//拉低电平60-120us内
			Delay_us(100);
			DS18B20_High();				//上拉电阻拉高防抖
			Delay_us(2);
		}
		dat >>= 1;
	}
	DS18B20_In();							//释放总线
}

/**
  * @brief  用于执行读命令
  * @param  None
  * @retval 返回读取的数据
  */
uint8_t DS18B20_Read(){
	uint16_t bit=0,dat=0;
	for(int i=0;i<8;i++){
		DS18B20_Out();							//控制总线
		DS18B20_Low();							//拉低总线
		Delay_us(2);
		DS18B20_In();								//释放总线
		Delay_us(12);								//读取总线电平，尽量贴近15us末尾
		bit=DS18B20_ReadStatus();		//读取总线电平
		Delay_us(50);								//所有读时序必须至少需要60us
		DS18B20_High();							//每两次读时隙之间至少需要>1us的恢复时间
		Delay_us(2);
		dat |= (bit<<i);
	}
	return dat;
}

/**
  * @brief  读取温度数据
  * @param  temp:指向存储温度数据的指针
	* @retval 返回操作结果，成功为1，失败为0
  */
uint8_t DS18B20_ReadData(float *temp){
	DS18B20_Init();
	if(DS18B20_Check()){
		DS18B20_Write(0xcc);						//跳过ROM
		DS18B20_Write(0x44);						//开始转换
	}else{
		return 0;
	}
	Delay_ms(50);											//等待转换完成
	DS18B20_Init();
	if(DS18B20_Check()){
		DS18B20_Write(0xcc);						//跳过ROM
		DS18B20_Write(0xbe);						//发送读寄存器命令
		uint8_t TL=DS18B20_Read();
		uint8_t TH=DS18B20_Read();
		uint16_t dat=(TH<<8)|TL;
		*temp=dat*0.0625;
		return 1;
	}else{
		return 0;
	}
}
